#include <stdio.h>
#define EI_MAG0     0   /* File identification byte 0 index 0x7f */
#define EI_MAG1     1   /* File identification byte 1 index 'E'*/
#define EI_MAG2     2   /* File identification byte 2 index ‘L’*/
#define EI_MAG3     3   /* File identification byte 3 index 'F'*/
#define EI_CLASS    4   /* File class */
#define ELFCLASSNONE      0 /* Invalid class */
#define ELFCLASS32        1 /* 32-bit objects */
#define ELFCLASS64        2 /* 64-bit objects */
#define EI_DATA     5   /* Data encoding */
#define EI_VERSION  6   /* File version */
#define EI_OSABI    7   /* Operating System/ABI indication */
#define EI_ABIVERSION   8   /* ABI version */
#define EI_PAD      9   /* Start of padding bytes */

char buff[16][20] ={
	"0x7f",
	"E",
	"L",
	"F",
	"0,1:elf32,2:elf64",
	"0:NUL,1:lit,2:big",
	"0:in ELF,1:Cu Ver",
	"OS/ABI indication",
};

#define EI_NIDENT   16

typedef unsigned long long elf_vma;
typedef unsigned long bfd_size_type;
typedef unsigned long bfd_vma;

typedef struct elf_internal_ehdr {
  unsigned char     e_ident[EI_NIDENT]; /* ELF "magic number" */
  bfd_vma       e_entry;    /* Entry point virtual address */
  bfd_size_type     e_phoff;    /* Program header table file offset */
  bfd_size_type     e_shoff;    /* Section header table file offset */
  unsigned long     e_version;  /* Identifies object file version */
  unsigned long     e_flags;    /* Processor-specific flags */
  unsigned short    e_type;     /* Identifies object file type */
  unsigned short    e_machine;  /* Specifies required architecture */
  unsigned int      e_ehsize;   /* ELF header size in bytes */
  unsigned int      e_phentsize;    /* Program header table entry size */
  unsigned int      e_phnum;    /* Program header table entry count */
  unsigned int      e_shentsize;    /* Section header table entry size */
  unsigned int      e_shnum;    /* Section header table entry count */
  unsigned int      e_shstrndx; /* Section header string table index */
} Elf_Internal_Ehdr;

typedef struct {
  unsigned char e_ident[16];        /* ELF "magic number" */
  unsigned char e_type[2];      /* Identifies object file type */
  unsigned char e_machine[2];       /* Specifies required architecture */
  unsigned char e_version[4];       /* Identifies object file version */
  unsigned char e_entry[4];     /* Entry point virtual address */
  unsigned char e_phoff[4];     /* Program header table file offset */
  unsigned char e_shoff[4];     /* Section header table file offset */
  unsigned char e_flags[4];     /* Processor-specific flags */
  unsigned char e_ehsize[2];        /* ELF header size in bytes */
  unsigned char e_phentsize[2];     /* Program header table entry size */
  unsigned char e_phnum[2];     /* Program header table entry count */
  unsigned char e_shentsize[2];     /* Section header table entry size */
  unsigned char e_shnum[2];     /* Section header table entry count */
  unsigned char e_shstrndx[2];      /* Section header string table index */
} Elf32_External_Ehdr;

typedef struct {
  unsigned char e_ident[16];        /* ELF "magic number" */
  unsigned char e_type[2];      /* Identifies object file type */
  unsigned char e_machine[2];       /* Specifies required architecture */
  unsigned char e_version[4];       /* Identifies object file version */
  unsigned char e_entry[8];     /* Entry point virtual address */
  unsigned char e_phoff[8];     /* Program header table file offset */
  unsigned char e_shoff[8];     /* Section header table file offset */
  unsigned char e_flags[4];     /* Processor-specific flags */
  unsigned char e_ehsize[2];        /* ELF header size in bytes */
  unsigned char e_phentsize[2];     /* Program header table entry size */
  unsigned char e_phnum[2];     /* Program header table entry count */
  unsigned char e_shentsize[2];     /* Section header table entry size */
  unsigned char e_shnum[2];     /* Section header table entry count */
  unsigned char e_shstrndx[2];      /* Section header string table index */
} Elf64_External_Ehdr;



void
byte_get_64 (unsigned char *field, elf_vma *high, elf_vma *low)
{
  if (byte_get == byte_get_big_endian)
    {
      *high = byte_get_big_endian (field, 4);
      *low = byte_get_big_endian (field + 4, 4);
    }
  else
    {
      *high = byte_get_little_endian (field + 4, 4);
      *low = byte_get_little_endian (field, 4);
    }
  return;
}

int main(int argc, char*argv[])
{
	Elf_Internal_Ehdr elf_header;
	FILE * file;
	int is_32bit_elf = 0;
	
	printf("filename: %s\n",argv[1]);
	file = fopen (argv[1], "rb");
    if (fread (elf_header.e_ident, EI_NIDENT, 1, file) != 1)
		return 0;
	
	for(int i= 0; i < EI_NIDENT; i++)
		printf("i=%2d  %2.2x : %s\n", i, elf_header.e_ident[i], buff[i]);
		
	is_32bit_elf = (elf_header.e_ident[EI_CLASS] != ELFCLASS64);

	if(is_32bit_elf)
	{
		Elf32_External_Ehdr ehdr32;
		if(fread(ehdr32.e_type, sizeof(ehdr32)-EI_NIDENT, 1,file)!=1)
			return 0;
		elf_header.e_type      = BYTE_GET (ehdr32.e_type);
		elf_header.e_machine   = BYTE_GET (ehdr32.e_machine);
		elf_header.e_version   = BYTE_GET (ehdr32.e_version);
		elf_header.e_entry     = BYTE_GET (ehdr32.e_entry);
		elf_header.e_phoff     = BYTE_GET (ehdr32.e_phoff);
		elf_header.e_shoff     = BYTE_GET (ehdr32.e_shoff);
		elf_header.e_flags     = BYTE_GET (ehdr32.e_flags);
		elf_header.e_ehsize    = BYTE_GET (ehdr32.e_ehsize);
		elf_header.e_phentsize = BYTE_GET (ehdr32.e_phentsize);
		elf_header.e_phnum     = BYTE_GET (ehdr32.e_phnum);
		elf_header.e_shentsize = BYTE_GET (ehdr32.e_shentsize);
		elf_header.e_shnum     = BYTE_GET (ehdr32.e_shnum);
		elf_header.e_shstrndx  = BYTE_GET (ehdr32.e_shstrndx);
		printf("32:%x\n", elf_header.e_type);
	}
	else
	{
		Elf64_External_Ehdr ehdr64;
		if(fread(ehdr64.e_type, sizeof(ehdr64)-EI_NIDENT, 1,file)!=1)
			return 0;
		elf_header.e_type      = BYTE_GET (ehdr64.e_type);
		elf_header.e_machine   = BYTE_GET (ehdr64.e_machine);
		elf_header.e_version   = BYTE_GET (ehdr64.e_version);
		elf_header.e_entry     = BYTE_GET (ehdr64.e_entry);
		elf_header.e_phoff     = BYTE_GET (ehdr64.e_phoff);
		elf_header.e_shoff     = BYTE_GET (ehdr64.e_shoff);
		elf_header.e_flags     = BYTE_GET (ehdr64.e_flags);
		elf_header.e_ehsize    = BYTE_GET (ehdr64.e_ehsize);
		elf_header.e_phentsize = BYTE_GET (ehdr64.e_phentsize);
		elf_header.e_phnum     = BYTE_GET (ehdr64.e_phnum);
		elf_header.e_shentsize = BYTE_GET (ehdr64.e_shentsize);
		elf_header.e_shnum     = BYTE_GET (ehdr64.e_shnum);
		elf_header.e_shstrndx  = BYTE_GET (ehdr64.e_shstrndx);
		printf("64:%x\n",elf_header.e_type);
	}

	printf("\n");
	return 0;
}
